type GetHardwareType = (module_id: string) => {write:Function};
type GetModulePinsType = (module_id: string) => string;

function timeout(ms:number) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

function getHardwareID(key: string){
    return (<any>window).getModuleID(key)[0][1]
}

export function get_functions(get_hardware:GetHardwareType, get_module_pins_value:GetModulePinsType) {
  return {
    kittenbot_microbit_robotbit_scroll(args:any, id:any, targetid:any, util:any) {
        const hardware = get_hardware(getHardwareID('kittenbot_microbit_robotbit_scroll'))
        hardware.write(`M1 ${args.TEXT}`);
    },
    kittenbot_microbit_robotbit_button(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_button'))
        let ret = false;
        if (hardware.btnValue === 3){
            ret = true;
        } else if (args.BUTTON === 'A'){
            ret = hardware.btnValue === 0x1;
        } else if (args.BUTTON === 'B'){
            ret = hardware.btnValue === 0x2;
        }
        if (ret) hardware.btnValue = 0; // cosume previous value
        return ret;
    },
    kittenbot_microbit_robotbit_digiwrite(args:any) {
        const hardware = get_hardware(getHardwareID('kittenbot_microbit_robotbit_digiwrite'))
        hardware.write(`M7 ${args.PIN} ${args.LEVEL}`);
    },
    kittenbot_microbit_robotbit_digiread(args:any) {
        const hardware = get_hardware(getHardwareID('kittenbot_microbit_robotbit_digiread'))
        hardware.write(`M9 ${args.PIN}`, (ret:string) => parseInt(ret, 10));
    },
    kittenbot_microbit_robotbit_analogwrite(args:any) {
        const hardware = get_hardware(getHardwareID('kittenbot_microbit_robotbit_analogwrite'))
        hardware.write(`M8 ${args.PIN} ${args.VALUE}`);
    },
    kittenbot_microbit_robotbit_analogread(args:any) {
        const hardware = get_hardware(getHardwareID('kittenbot_microbit_robotbit_analogread'))
        hardware.write(`M10 ${args.PIN}`, (ret:string) => parseInt(ret, 10));
    },
    kittenbot_microbit_robotbit_pinpull(args:any) {

    },
    kittenbot_microbit_robotbit_playmusic(args:any) {
        const hardware = get_hardware(getHardwareID('kittenbot_microbit_robotbit_playmusic'))
        hardware.write(`M14 ${args.MUSIC}`);
    },
    kittenbot_microbit_robotbit_tone(args:any) {
        const hardware = get_hardware(getHardwareID('kittenbot_microbit_robotbit_tone'))
        hardware.write(`M11 ${args.FREQ} ${args.LEN}`);
    },
    kittenbot_microbit_robotbit_imu(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_imu'))
        if (args.DIRECTION === 'x'){
            return hardware.accX;
        } else if (args.DIRECTION === 'y'){
            return hardware.accY;
        } else if (args.DIRECTION === 'z'){
            return hardware.accZ;
        }
    },
    kittenbot_microbit_robotbit_gesture(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_gesture'))
        return hardware.gesValue === args.GESTURE;
    },
    kittenbot_microbit_robotbit_compass(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_compass'))
        hardware.write(`M16`, (ret:string) => parseInt(ret, 10));
    },
    kittenbot_microbit_robotbit_radio(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_radio'))
        hardware.write(`M61 ${args.SWITCH}`);
    },
    kittenbot_microbit_robotbit_radioch(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_radioch'))
        hardware.write(`M62 ${args.CHANNEL}`);
    },
    kittenbot_microbit_robotbit_radiosend(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_radiosend'))
        hardware.write(`M63 ${args.TEXT}`);
    },
    kittenbot_microbit_robotbit_radiogot(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_radiogot'))
        let ret = '';
        if (hardware.radioRx){
            ret = hardware.radioRx.replace(/[^\x00-\x7F]/g, '');
            hardware.radioRx = null;
        }
        return ret;
    },
    kittenbot_microbit_robotbit_motorrun(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_motorrun'))
        hardware.write(`M21 ${args.MOTOR} ${args.SPEED} 0`);
    },
    async kittenbot_microbit_robotbit_motorrundelay(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_motorrundelay'))
        hardware.write(`M21 ${args.MOTOR} ${args.SPEED} ${args.DELAY}`);
        await timeout(args.DELAY);
    },
    kittenbot_microbit_robotbit_motorstop(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_motorstop'))
        hardware.write(`M22 ${args.MOTOR}`);
    },
    kittenbot_microbit_robotbit_stepper(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_stepper'))
        hardware.write(`M25 ${args.DEG1} ${args.DEG2}`);
    },
    kittenbot_microbit_robotbit_servo(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_servo'))
        const ch = parseInt(args.CHANNEL, 10) - 1
        hardware.write(`M24 ${ch} ${args.DEGREE} 0`);
    },
    kittenbot_microbit_robotbit_servogeek(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_servogeek'))
        const ch = parseInt(args.CHANNEL, 10) - 1
        hardware.write(`M24 ${ch} ${args.DEGREE} 1`);
    },
    kittenbot_microbit_robotbit_rgbcolor(args:any) {
        const hexToRgb = (hex:string) => {
            const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
            return result ? {
                r: parseInt(result[1], 16),
                g: parseInt(result[2], 16),
                b: parseInt(result[3], 16)
            } : null;
        };
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_rgbcolor'))
        let idx = args.INDEX;
        const c:any = hexToRgb(args.COLOR);
        if (idx === 'All'){
            idx = -1;
        } else {
            idx = parseInt(idx) - 1;
        }
        hardware.write(`M31 ${idx} ${c.r} ${c.g} ${c.b}`);
    },
    kittenbot_microbit_robotbit_rgbshow(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_rgbshow'))
        hardware.write(`M30`);
    },
    kittenbot_microbit_robotbit_rgbclear(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_rgbclear'))
        hardware.write(`M32`);
    },
    kittenbot_microbit_robotbit_distance(args:any) {
        const hardware:any = get_hardware(getHardwareID('kittenbot_microbit_robotbit_distance'))
        if (hardware.usPin !== args.PIN){
            hardware.usPin = args.PIN;
            const pin = parseInt(args.PIN[1], 10);
            hardware.write(`M15 ${pin}`);
        }
        return hardware.usValue;
    },
  }
}